﻿using System.Text.Json.Serialization;

namespace EasyDDD.AdminModule.Application.QueriesSysMenu
{
    public record SysMenuGetUserRouteQuery : IQuery<List<SysMenuGetUserRouteQueryResult>>
    {
        [JsonIgnore]
        [NotMapped]
        public System.Security.Claims.ClaimsPrincipal User { get; set; } = default!;
    }

    [AutoMapperFrom(typeof(Models.SysMenu))]
    public record SysMenuGetUserRouteQueryResult : Models.SysMenu
    {
        /// <summary>
        /// 软删除
        /// </summary>
        [NotMapped]
        public override bool IsDeleted { get; set; } = default!;

        /// <summary>
        /// 租户ID
        /// </summary>
        [NotMapped]
        public override Guid TenantId { get; set; } = default!;
    }

    public class SysMenuGetUserRouteQueryHandler(
       IMapper mapper,
       Records.SysMenuRecords sysMenuRecords,
       Records.SysAdminRoleRecords sysAdminRoleRecords,
       ILogger<SysMenuGetUserRouteQueryHandler> logger)
       : IQueryHandler<SysMenuGetUserRouteQuery, List<SysMenuGetUserRouteQueryResult>>
    {
        public async Task<List<SysMenuGetUserRouteQueryResult>> Handle(SysMenuGetUserRouteQuery request, CancellationToken cancellationToken)
        {
            logger.LogDebug("查询 SysMenuGetUserRouteQueryHandler");
            var menuTypes = new short[] { 0, 1, 2 };
            if (request.User.IsInRole("superadmin") || request.User.HasClaim(ClaimTypes.Role, "superadmin"))
            {
                var query = sysMenuRecords.AsQueryable();
                query = query.Where(e => menuTypes.Contains(e.MenuType));

                query = query.OrderBy(e => e.Id);
                return await mapper.ProjectTo<SysMenuGetUserRouteQueryResult>(query).ToListAsync(cancellationToken);
            }
            else
            {
                var roles = request.User.Claims.Where(e => e.Type == ClaimTypes.Role).Select(e => e.Value);
                var menuIds = await sysAdminRoleRecords.AsQueryable().Where(e => roles.Contains(e.Code)).SelectMany(e => e.MenuList.Select(f => f.SysMenuId)).ToArrayAsync();
                var query = sysMenuRecords.AsQueryable();
                query = query.Where(e => menuIds.Contains(e.Id) && menuTypes.Contains(e.MenuType));

                query = query.OrderBy(e => e.Id);
                return await mapper.ProjectTo<SysMenuGetUserRouteQueryResult>(query).ToListAsync(cancellationToken);
            }
        }
    }
}
